#include "FPCH.h"

#include "FTextDisplayOpenGL.h"

#include "FTexture.h"

namespace Font
{

	TextDisplayOpenGL::TextDisplayOpenGL(Library* a_Library, unsigned int a_Amount) : TextDisplay(a_Library)
	{
		m_GlyphTotal = 0;

		m_Position = NULL;
		m_PositionFilled = m_PositionTotal = 0;

		m_TexCoord = NULL;
		m_TexCoordFilled = m_TexCoordTotal = 0;

		m_VertexFilled = NULL;
		m_VertexFilled = m_VertexTotal = 0;
		m_VertexStart = 0;

		Clear();
		Reserve(a_Amount);
	}

	TextDisplayOpenGL::~TextDisplayOpenGL()
	{
		if (m_Position) { delete [] m_Position; }
		if (m_TexCoord) { delete [] m_TexCoord; }
		if (m_VertexIndices) { delete [] m_VertexIndices; }
	}
	
	void TextDisplayOpenGL::Clear()
	{
		m_PositionFilled = 0;
		m_TexCoordFilled = 0;
		m_VertexStart = 0;
		m_VertexFilled = 0;
	}

	void TextDisplayOpenGL::Reserve(unsigned int a_Amount)
	{
		if (a_Amount < m_GlyphTotal) 
		{ 
			return; 
		}

		if (m_GlyphTotal == 0)
		{
			m_GlyphTotal = a_Amount;

			m_PositionFilled = 0;
			m_PositionTotal = m_GlyphTotal * 4;
			m_Position = new tb::Vec2[m_PositionTotal];

			m_TexCoordFilled = 0;
			m_TexCoordTotal = m_GlyphTotal * 4;
			m_TexCoord = new tb::Vec2[m_TexCoordTotal];

			m_VertexFilled = 0;
			m_VertexStart = 0;
			m_VertexTotal = m_GlyphTotal * 6;
			m_VertexIndices = new unsigned int[m_VertexTotal];

			return;
		}

		unsigned int vertex_total = a_Amount * 4;
		unsigned int indices_total = a_Amount * 6;

		// resize position data

		tb::Vec2* temp_pos = new tb::Vec2[vertex_total];
		tb::Vec2* dst_pos = temp_pos;
		tb::Vec2* src_pos = m_Position;

		for (unsigned int i = 0; i < m_PositionFilled; i++)
		{
			*dst_pos = *src_pos;
		}

		delete [] m_Position;
		m_Position = temp_pos;
		m_PositionTotal = vertex_total;

		// resize texcoord data

		tb::Vec2* temp_texcoord = new tb::Vec2[vertex_total];
		tb::Vec2* dst_texcoord = temp_texcoord;
		tb::Vec2* src_texcoord = m_TexCoord;

		for (unsigned int i = 0; i < m_TexCoordFilled; i++)
		{
			*dst_texcoord = *src_texcoord;
		}

		delete [] m_TexCoord;
		m_TexCoord = temp_texcoord;
		m_TexCoordTotal = vertex_total;

		// resize indices

		unsigned int* temp_indices = new unsigned int[indices_total];
		unsigned int* dst_indices = temp_indices;
		unsigned int* src_indices = m_VertexIndices;

		for (unsigned int i = 0; i < m_VertexFilled; i++)
		{
			*dst_indices = *src_indices;
		}

		delete [] m_VertexIndices;
		m_VertexIndices = temp_indices;
		m_VertexTotal = indices_total;

		// finish

		m_GlyphTotal = a_Amount;
	}

	void TextDisplayOpenGL::AddPosition(float a_X, float a_Y)
	{
		if (m_PositionFilled == m_PositionTotal) { return; }

		m_Position[m_PositionFilled].x = a_X;
		m_Position[m_PositionFilled].y = a_Y;
		m_PositionFilled++;
	}

	void TextDisplayOpenGL::AddTexCoord(float a_X, float a_Y)
	{
		if (m_TexCoordFilled == m_TexCoordTotal) { return; }

		m_TexCoord[m_TexCoordFilled].x = a_X;
		m_TexCoord[m_TexCoordFilled].y = a_Y;
		m_TexCoordFilled++;
	}

	void TextDisplayOpenGL::NextQuad()
	{
		if (m_VertexFilled == m_VertexTotal) { return; }

		m_VertexIndices[m_VertexFilled++] = m_VertexStart + 0;
		m_VertexIndices[m_VertexFilled++] = m_VertexStart + 1;
		m_VertexIndices[m_VertexFilled++] = m_VertexStart + 2;

		m_VertexIndices[m_VertexFilled++] = m_VertexStart + 1;
		m_VertexIndices[m_VertexFilled++] = m_VertexStart + 3;
		m_VertexIndices[m_VertexFilled++] = m_VertexStart + 2;

		m_VertexStart = m_PositionFilled;
	}

	void TextDisplayOpenGL::Render()
	{
		m_Page->GetTexture()->Bind();

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glVertexPointer(2, GL_FLOAT, 0, m_Position);
		glTexCoordPointer(2, GL_FLOAT, 0, m_TexCoord);

		glDrawElements(GL_TRIANGLES, m_VertexFilled, GL_UNSIGNED_INT, m_VertexIndices);

		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);
	}

}; // namespace Font